#ifndef SPEED_CNTR_H
#define SPEED_CNTR_H

#include "user_global.h"
#include "freq_table.h"


/*--------------------Z Motor-----------------------------*/
// Z方向电机
#define IO_Z_DIR(act)                       HAL_GPIO_WritePin(CW_GPIO_Port, CW_Pin,(FlagStatus)act)
// 电机使能 1为失能 0为使能
#define IO_Z_ENABLE(act)                    HAL_GPIO_WritePin(EN_GPIO_Port, EN_Pin, (FlagStatus)!act)

#define IO_Z_M1(act)                        HAL_GPIO_WritePin(M1_GPIO_Port, M1_Pin, (FlagStatus)act)
#define IO_Z_M2(act)                        HAL_GPIO_WritePin(M2_GPIO_Port, M2_Pin, (FlagStatus)act)
#define IO_Z_M3(act)                        HAL_GPIO_WritePin(M3_GPIO_Port, M3_Pin, (FlagStatus)act)
#define IO_Z_PFD(act);                      HAL_GPIO_WritePin(LOCK_GPIO_Port, LOCK_Pin, (FlagStatus)act)


#define IO_Z_HOME                           !HAL_GPIO_ReadPin(Z_RESET_GPIO_Port,Z_RESET_Pin)
#define Z_AT_HOME                           IO_Z_HOME
#define DRAW_AT_CLOSE                       IO_Z_HOME

#define IO_Z_LIMIT                          !HAL_GPIO_ReadPin(Z_LIMIT_GPIO_Port,Z_LIMIT_Pin)
#define Z_AT_LIMIT                          IO_Z_LIMIT
#define DRAW_AT_OPEN                        IO_Z_LIMIT

struct SpeedRampData;

typedef void (*SPEED_CALLBACK)(uchar role);
typedef void (*STEP_UPDATE)(uchar role);
typedef void (*PULSE_PROC)(uchar role,uchar level);
typedef void (*TIMER_PROC)(uchar role);
typedef void (*STOP_TIMER)(uchar role);
typedef void (*SRD_PROC)(struct SpeedRampData *srd);


typedef struct SpeedRampData
{
    uchar run_state : 3;        // What part of the speed ramp we are in.
    uchar dir : 1;              // Direction stepper motor should move.
    uchar running : 1;          // 电机正在运行
    uchar need_cleanup : 1;     // 需要运行清除函数
    uchar home_state : 1;       // 原点传感器状态
    uchar limit_state :1;
    uchar limit_state2 :1;
    uchar limit_state3 :1;
    uchar hit_home : 1;         // 运行经过原点
    uchar hit_limit : 1;        // 运行经过限位1
    uchar hit_limit2 : 1;       // 运行经过限位2
    uchar hit_limit3 : 1;       // 运行经过限位3
    uchar coder_self : 1;       // 脉冲计数方式 0：编码器计数 1：定时器自身计数

    ushort speed_index;         // Counter used when accelerateing/decelerateing to calculate step_delay.
    ushort max_index;           // 频率表最大索引
    long step_left;             // 电机剩余运行步数
    ulong step_count;           // Counting steps when moving.
    ulong start_time;           // 开始运行时间
    signed char step_offset;    // 每走一步的增量, +/-1
    long target;                // 目标坐标
    long max_target;            // 最大目标坐标
    uchar micro;                // 当前电机细分, 为0时表示使用默认16细分
    ushort first_stage_speed;   // 开始阶段低速运行的速度索引
    ushort first_stage_step;    // 开始阶段低速运行的步数
    ushort second_stage_speed;  // 结束阶段低速运行的速度索引
    ushort second_stage_step;   // 结束阶段低速运行的步数

    ulong stamp;
    long pos;                   // 运动前的初始位置
    uchar role;                 // 当前电机属性名
    uchar micro_step;           // 细分脉冲计步步数
    long reset_step;            // 电机运行时感应到复位传感器后的缓冲步数
    long limit_step;            // 电机运行时感应到限位传感器后的缓冲步数
    long stop_step;             // 按键控制电机停止时的缓冲步数
    long limit_target;          // 电机运行时的最大目标位置
    long v_lock_pos;            // 电磁阀锁定位置，离开复位位置时，由释放状态变为锁定状态的位置
    long v_release_pos;         // 电磁阀释放位置，向复位位置时，由锁定状态变为释放状态的位置
    uint32_t reset_monitor_step;// 复位监管步数

    SPEED_CALLBACK init;        // 电机启动前调用的初始化函数
    SPEED_CALLBACK update;      // 每走一步调用的函数
    SPEED_CALLBACK cleanup;     // 停止后调用的函数
    PULSE_PROC step;            // step信号输出
    TIMER_PROC start_timer;     // 更新定时器
    STOP_TIMER stop_timer;      // 停止定时器
} SpeedRampData;

typedef struct SRD_DESC
{
    uint32_t timer;
    uint16_t timer_ch;
    uchar home;                      // 表示复位光耦,对应 GPIO_IN 中的传感器 ID值
    uchar limit;                     // 表示限位光耦,对应 GPIO_IN 中的传感器 ID值
    uchar limit2;                    // 表示限位光耦,对应 GPIO_IN 中的传感器 ID值
    uchar limit3;                    // 表示限位光耦,对应 GPIO_IN 中的传感器 ID值
    SpeedRampData *srd;
} SRD_DESC;

extern SRD_DESC srd_desc[MACHINE_COUNT];

// 执行动作定义
enum ACTION
{
    STANDBY = 0000,                            // 取消当前执行动作.
    MRESET,                                    // 复位. 复位所有抽屉和上盖.
    OPEN_S1_DRAWER,                            // 打开杯盘抽屉, 如果在打开位置，不动作
    CLOSE_S1_DRAWER,                           // 关闭杯盘抽屉，如果在关闭位置，不动作
    OPEN_S2_DRAWER,                            // 打开左试剂抽屉, 如果在打开位置，不动作
    CLOSE_S2_DRAWER,                           // 关闭左试剂抽屉，如果在关闭位置，不动作
    OPEN_S3_DRAWER,                            // 打开右试剂抽屉, 如果在打开位置，不动作
    CLOSE_S3_DRAWER,                           // 关闭右试剂抽屉，如果在关闭位置，不动作
    OPEN_S4_DRAWER,                            // 打开上盖, 如果在打开位置，不动作
    CLOSE_S4_DRAWER,                           // 关闭上盖，如果在关闭位置，不动作
    RESET_S1,                                  // 复位S1, 向原点方向移动，然后移动到抽屉关闭位置
    RESET_S2,                                  // 复位S2, 向原点方向移动，然后移动到抽屉关闭位置
    RESET_S3,                                  // 复位S3, 向原点方向移动，然后移动到抽屉关闭位置
    RESET_S4,                                  // 复位S4, 向原点方向移动，然后移动到关闭位置
    DISABLE_MOTOR,                             // 解锁所有电机. 并取消所有电磁阀锁定
#ifdef PRODUCT_DEBUG
    S_MOVE_TO
#endif
    CONFIG_S1_PARAM,                           // 复位S1, 向原点方向移动，然后移动到抽屉关闭位置
    CONFIG_S2_PARAM,                           // 复位S2, 向原点方向移动，然后移动到抽屉关闭位置
    CONFIG_S3_PARAM,                           // 复位S3, 向原点方向移动，然后移动到抽屉关闭位置
    CONFIG_S4_PARAM,                           // 复位S4, 向原点方向移动，然后移动到关闭位置
};

// 状态定义
enum MACHINE_STATUS
{
    S1_STATUS_HOME_SENSOR_ERROR = 1,    // 0001 S1复位传感器故障. 1: 故障 0: 正常
    S2_STATUS_HOME_SENSOR_ERROR,        // 0002 S2复位传感器故障. 1: 故障 0: 正常
    S3_STATUS_HOME_SENSOR_ERROR,        // 0003 V1复位传感器故障. 1: 故障 0: 正常
    S4_STATUS_HOME_SENSOR_ERROR,        // 0004 V2复位传感器故障. 1: 故障 0: 正常
    S1_STATUS_LIMIT_SENSOR_ERROR,       // 0005 S1限位传感器故障. 1: 故障 0: 正常
    S2_STATUS_LIMIT_SENSOR_ERROR,       // 0006 S2限位传感器故障. 1: 故障 0: 正常
    S3_STATUS_LIMIT_SENSOR_ERROR,       // 0007 S1限位传感器故障. 1: 故障 0: 正常
    S4_STATUS_LIMIT_SENSOR_ERROR,       // 0008 S2限位传感器故障. 1: 故障 0: 正常
    S1_STATUS_MOTOR_ERROR,              // 0009 S1电机故障. 1: 故障 0: 正常
    S2_STATUS_MOTOR_ERROR,              // 000A S1电机故障. 1: 故障 0: 正常
    S3_STATUS_MOTOR_ERROR,              // 000B S1电机故障. 1: 故障 0: 正常
    S4_STATUS_MOTOR_ERROR,              // 000C S1电机故障. 1: 故障 0: 正常
};

// Speed ramp states
#define MOTION_STATE_STOP       0
#define MOTION_STATE_ACCEL      1
#define MOTION_STATE_DECEL      2
#define MOTION_STATE_RUN        3

#define CCW                     0   // 反向
#define CW                      1   // 正向

extern SpeedRampData srd[MACHINE_COUNT];

void speed_cntr_Move(SpeedRampData *srd, long step, unsigned int speed);
void speed_update(uchar role);
void Move_To_Update(uchar role);
void InitMachine(void);
void Set_Timer(uchar role);
void Stop_Timer(uchar role);
void Step(uchar role,uchar level);
void Do_Action_Move_To(uchar role, long target, ushort speed);
void Do_Action_T_Trans_To_Target(uchar role,long target,ushort speed);
void Do_Action_Home(void);
void Do_Action_T1_Trans_Out(void);
void Do_Action_Stop(uchar role);

#define SPEED2INDEX(speed)      (ushort)((ulong)(speed) * (speed) * ( 1 / (2 * ALPHA * ACCEL * 100)))
#define DISTANCE2STEP(d)        (ushort)((d) / S1_PERIMETER * SPR)

#endif
